package com.clusterconfig.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class Main extends Composite {

	private static MainUiBinder uiBinder = GWT.create(MainUiBinder.class);

	interface MainUiBinder extends UiBinder<Widget, Main> { }

	@UiField
	ListBox lbField;
	
	@UiField
	ListBox jbossTypeField;
	
	@UiField Label architectureLabel;
	@UiField ListBox architectureField;
	
	@UiField Label jbossVersionLabel;
	@UiField ListBox jbossVersionField;
	
	@UiField Label apacheVersionLabel;
	@UiField ListBox apacheVersionField;
	
	@UiField Label modJkVersionLabel;
	@UiField ListBox modJkVersionField;
	
	@UiField Label modClusterVersionLabel;
	@UiField ListBox modClusterVersionField;
	
	@UiField Label modClusterAdvertiseLabel;
	@UiField ListBox modClusterAdvertiseField;
	
	@UiField
	TextBox numberJBossInstancesField;
	
	@UiField
	TextBox ipAddressesField;
	
	@UiField Button generateButton;
	
	@UiField VerticalPanel output;
	
	final TextArea bashScriptTextArea = new TextArea();

	public Main() {
		initWidget(uiBinder.createAndBindUi(this));
		
		addItemsToListBox(lbField, 
				"mod_jk",
				"mod_proxy",
				"mod_cluster");
		lbField.setItemSelected(0, true);
		
	    
	    addItemsToListBox(jbossTypeField, 
	    		"Enterprise",
	    		"Community");
	    jbossTypeField.setItemSelected(0, true);

	    architectureLabel.setText("Architecture");
	    architectureField.addItem("RHEL 5 / Fedora x86_64", "rhel5_64");
	    architectureField.addItem("RHEL 5 / Fedora i386","rhel5_32");
	    architectureField.addItem("RHEL 4 x86_64","rhel4_64");
	    architectureField.addItem("RHEL 4 i386","rhel4_32");
	    architectureField.addItem("Other Linux x86_64", "other_linux_64");
	    architectureField.addItem("Other Linux i386","other_linux_32");
	    architectureField.setItemSelected(0, true);
		
		//jbossVersionField
	    //TODO change to addItemsToList(jbossVersionField, getAllEAPReleases);
	    jbossVersionLabel.setText("JBoss version");
		addAllEAPReleases();
		jbossVersionField.setItemSelected(0, true);
		
		apacheVersionLabel.setText("Apache version");
		addItemsToListBox(apacheVersionField, 
				"2.2.15",
				"2.2.14",
				"2.2.13",
				"2.2.12",
				"2.2.11",
				"2.2.0");
		apacheVersionField.setItemSelected(0, true);

		modJkVersionLabel.setText("mod_jk version");
		addItemsToListBox(modJkVersionField, 
				"1.2.30",
				"1.2.28");
		modJkVersionField.setItemSelected(0, true);
	    
		modClusterVersionLabel.setText("mod_cluster version");
		setVisible(false, modClusterVersionLabel, modClusterVersionField);
		addItemsToListBox(modClusterVersionField, 
				"1.1.0.CR3",
				"1.0.4.GA",
				"1.0.3.GA");
		modClusterVersionField.setItemSelected(0, true);
	    
		modClusterAdvertiseLabel.setText("mod_cluster advertise");
		setVisible(false, modClusterAdvertiseLabel, modClusterAdvertiseField);
	    modClusterAdvertiseField.addItem("multicast advertise (default)", "true");
	    modClusterAdvertiseField.addItem("proxyList / multicast disabled", "false");
		modClusterAdvertiseField.setItemSelected(0, true);
	    
	    numberJBossInstancesField.setText("1");
	    numberJBossInstancesField.selectAll();
	    numberJBossInstancesField.setMaxLength(2);
	    numberJBossInstancesField.setSize("25px", "");
	    
	    ipAddressesField.setText("127.0.0.1");
	    ipAddressesField.selectAll();
	    ipAddressesField.setSize("200px", "");
	    
	    generateButton.setText("Generate");
	}
	
	@UiHandler("generateButton")
	void generateButtonClick(ClickEvent e) {
		output.clear();
		generateScript();
	}
	
	@UiHandler("numberJBossInstancesField")
	void numberJBossInstancesFieldOnKeyUp(KeyUpEvent event) {
		int jbossInstances = Integer.valueOf(numberJBossInstancesField.getValue());
		String newFieldValue = "";
		for(int i = 1; i <= jbossInstances; i++) {
			newFieldValue += "127.0.0." + i;
			if(i != jbossInstances) {
				newFieldValue += ",";
			}
		}
		ipAddressesField.setText(newFieldValue);
	}

	@UiHandler("lbField")
	void lbFieldOnClick(ClickEvent e) {
		int lbFieldCurrentSelectedIndex = lbField.getSelectedIndex();
		if("mod_proxy".equals(lbField.getValue(lbField.getSelectedIndex()))) {
			setVisible(false, 
					modJkVersionLabel, modJkVersionField,
					modClusterVersionLabel, modClusterVersionField,
					architectureLabel, architectureField,
					modClusterAdvertiseLabel, modClusterAdvertiseField);
		} else if("mod_jk".equals(lbField.getValue(lbField.getSelectedIndex()))) {
			setVisible(true, modJkVersionLabel, modJkVersionField);
			setVisible(true, architectureLabel, architectureField);
			setVisible(false, 
					modClusterVersionLabel, modClusterVersionField,
					modClusterAdvertiseLabel, modClusterAdvertiseField);
		} else if("mod_cluster".equals(lbField.getValue(lbField.getSelectedIndex()))) {
			setVisible(false, modJkVersionLabel, modJkVersionField);
			setVisible(true, 
					architectureLabel, architectureField,
					modClusterAdvertiseLabel, modClusterAdvertiseField);
			if("Enterprise".equals(jbossTypeField.getValue(jbossTypeField.getSelectedIndex()))) {
				jbossVersionField.clear();
				addOnlyEAP5OrGreaterReleases();
			} else if("Community".equals(jbossTypeField.getValue(jbossTypeField.getSelectedIndex()))) {
				jbossVersionField.clear();
				addOnlyCommunityJBoss51OrGreaterReleases();
				setVisible(true, modClusterVersionLabel, modClusterVersionField);
			}
		}
	}
	
	@UiHandler("jbossVersionField")
	void jbossVersionFieldOnClick(ClickEvent e) {
		String jbossVersion = jbossVersionField.getValue(jbossVersionField.getSelectedIndex());
		String selectedLbField = lbField.getValue(lbField.getSelectedIndex());
		String jbossType = jbossTypeField.getValue(jbossTypeField.getSelectedIndex());
		int lbFieldSelectedIndex = lbField.getSelectedIndex();
		
		//Does this really do anything?
		if(jbossVersion.contains("4.")) {
			lbField.clear();
			lbField.addItem("mod_jk");
		    lbField.addItem("mod_proxy");
		    lbField.setSelectedIndex(0);
		} else {
			lbField.clear();
			lbField.addItem("mod_jk");
		    lbField.addItem("mod_proxy");
		    lbField.addItem("mod_cluster");
		    lbField.setSelectedIndex(lbFieldSelectedIndex);
		}
		
		if(jbossVersion.contains("6.") && selectedLbField.equals("mod_cluster") && jbossType.equals("Community")) {
			modClusterVersionField.clear();
			modClusterVersionField.addItem("1.1.0.CR2", "1.1.0.CR2");
			modClusterVersionField.setVisibleItemCount(1);
		    modClusterVersionField.setItemSelected(0, true);
		} 
		//TODO test 1.1 with 5 in the future
		else if (jbossVersion.contains("5.") && selectedLbField.equals("mod_cluster") && jbossType.equals("Community")) {
			modClusterVersionField.clear();
			modClusterVersionField.addItem("1.1.0.CR2", "1.1.0.CR2");
			modClusterVersionField.addItem("1.0.4.GA", "1.0.4.GA");
			modClusterVersionField.addItem("1.0.3.GA", "1.0.3.GA");
			modClusterVersionField.setVisibleItemCount(1);
		    modClusterVersionField.setItemSelected(0, true);
		}
	}
	
	@UiHandler("jbossTypeField")
	void jbossTypeFieldOnClick(ClickEvent e) {
		if("Enterprise".equals(jbossTypeField.getValue(jbossTypeField.getSelectedIndex()))) {
			if("mod_cluster".equals(lbField.getValue(lbField.getSelectedIndex()))){
				jbossVersionField.clear();
				addOnlyEAP5OrGreaterReleases();
				jbossVersionField.setItemSelected(0, true);
				setVisible(true, jbossVersionField);
			} else {
				jbossVersionField.clear();
				addAllEAPReleases();
				jbossVersionField.setItemSelected(0, true);
				setVisible(true, jbossVersionField);
			}
			setVisible(false, modClusterVersionLabel, modClusterVersionField);
		} else if("Community".equals(jbossTypeField.getValue(jbossTypeField.getSelectedIndex()))) {
			String selectedLbField = lbField.getValue(lbField.getSelectedIndex());
			if("mod_cluster".equals(selectedLbField)) {
				jbossVersionField.clear();
				addOnlyCommunityJBoss51OrGreaterReleases();
				jbossVersionField.setItemSelected(0, true);
				setVisible(true, jbossVersionLabel, jbossVersionField);
				String jbossVersion = jbossVersionField.getValue(jbossVersionField.getSelectedIndex());
				if(jbossVersion.contains("6.")) {
					modClusterVersionField.clear();
					modClusterVersionField.addItem("1.1.0.CR2", "1.1.0.CR2");
					modClusterVersionField.setVisibleItemCount(1);
				    modClusterVersionField.setItemSelected(0, true);
				    setVisible(true, modClusterVersionLabel, modClusterVersionField);
				} else {
					modClusterVersionField.clear();
					modClusterVersionField.addItem("1.1.0.CR2", "1.1.0.CR2");
					modClusterVersionField.addItem("1.0.4.GA", "1.0.4.GA");
					modClusterVersionField.addItem("1.0.3.GA", "1.0.3.GA");
					modClusterVersionField.setVisibleItemCount(1);
				    modClusterVersionField.setItemSelected(0, true);
				    setVisible(true, modClusterVersionLabel, modClusterVersionField);
				}
			} else {
				jbossVersionField.clear();
				addAllCommunityJBossReleases();
				jbossVersionField.setItemSelected(0, true);
				setVisible(true, jbossVersionField);
				setVisible(false, modClusterVersionLabel, modClusterVersionField);
			}
		}
	}
	
	protected void generateScript() {
		String jbossVersionSelected = jbossVersionField.getValue(jbossVersionField.getSelectedIndex());
		String apacheVersionSelected = apacheVersionField.getValue(apacheVersionField.getSelectedIndex());
		String loadbalancer = lbField.getValue(lbField.getSelectedIndex());
		String jbossInstances = numberJBossInstancesField.getValue();
		String jbossType = jbossTypeField.getValue(jbossTypeField.getSelectedIndex());
		String ipAddresses = ipAddressesField.getValue();
		String architecture = architectureField.getValue(architectureField.getSelectedIndex());
		
		if("Enterprise".equals(jbossTypeField.getValue(jbossTypeField.getSelectedIndex()))) {
			//nothing to do right now
		}
		
		String bashScript = "python clusterconfig.py --jboss-version " + jbossVersionSelected + " " +
		        "--jboss-type " + jbossType + " " +
		        "--jboss-instances " + jbossInstances + " " +
		        "--ip-addresses " + ipAddresses + " " +
				"--httpd-version " + apacheVersionSelected + " " +
				"--loadbalancer " + loadbalancer + " " +
				"--architecture " + architecture + " ";
		
		if("mod_jk".equals(loadbalancer)) {
			String modjkVersionSelected = modJkVersionField.getValue(modJkVersionField.getSelectedIndex());
			bashScript += "--modjk-version " + modjkVersionSelected + " ";
		} else if("mod_cluster".equals(loadbalancer)) {
			String modClusterVersionSelected = modClusterVersionField.getValue(modClusterVersionField.getSelectedIndex());
			String modClusterAdvertiseSelected = modClusterAdvertiseField.getValue(modClusterAdvertiseField.getSelectedIndex());
			if(!(modClusterVersionSelected.equals("5.0.0") || modClusterVersionSelected.equals("5.0.1")) && !jbossType.equals("Enterprise"))
				bashScript += "--modcluster-version " + modClusterVersionSelected + " ";
			if(null != modClusterAdvertiseSelected && !"".equals(modClusterAdvertiseSelected))
				bashScript += "--modcluster-advertise " + modClusterAdvertiseSelected + " ";
		}
		
		displayInstructionalTips();
		
		bashScriptTextArea.setReadOnly(true);
		bashScriptTextArea.setSize("850px", "100px");
		bashScriptTextArea.setText(bashScript);
		output.add(bashScriptTextArea);
		displayInformationalTips();
	}
	
	protected void displayInstructionalTips() {
		final HTML startScript = new HTML();
		startScript.setStyleName("info");
		startScript.setHTML("First download the <a href=\"python/clusterconfig.py\" target=\"_blank\">clusterconfig.py</a> script (Right click -> Save Link As) then copy and paste the below command into your terminal.  The script will automatically download or prompt you to download any necessary files like JBoss, mod_jk, ect...  All works " +
				"is done in a sandbox directory where the script was downloaded and files are saved in the sandbox directory + /archives for future use of the script.  After the script has finished setting everything up " +
				"it will spawn a terminal for each JBoss instance and start JBoss, then spawn a third terminal for Apache.  All you must do then is run the command <b>./apache.sh start</b> then open <a href=\"http://localhost/counter\">http://localhost/counter</a> " +
				"to verify everything is properly functioning.");
		output.add(startScript);
	}
	
	protected void displayInformationalTips() {
		String loadbalancer = lbField.getValue(lbField.getSelectedIndex());
		String modClusterAdvertiseSelected = modClusterAdvertiseField.getValue(modClusterAdvertiseField.getSelectedIndex());
		if("mod_cluster".equals(loadbalancer) && !"false".equals(modClusterAdvertiseSelected)) {
			final HTML someHtml = new HTML();
			someHtml.setHTML("Multicast traffic may be blocked by SELinux, see the <a href=\"http://www.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/5.0.1/html/Seam_Reference_Guide/ClusteringAndEJBPassivation.html#clustering.deployment\"> Red Hat EAP docs</a> for iptables rules to allow multicast for clustering. " +
					"Dealing with mod_cluster specifically you will want the following rule <br /><br />" +
					"/sbin/iptables -I INPUT 15 -p udp -d 224.0.1.0/24 -j ACCEPT<br />" + 
					"/etc/init.d/iptables save<br />");
			someHtml.setStyleName("warning");
			output.add(someHtml);
		}
		
		int jbossInstances = Integer.valueOf(numberJBossInstancesField.getValue());
		if(jbossInstances > 1) {
			final HTML someHtml = new HTML();
			someHtml.setHTML("An easy way to run multiple IPs on 1 machine for testing is to use the loopback device<br>" +
					"in rc.local add this:<br>" +
					"ifconfig lo:2 127.0.0.2<br />" +
					"ifconfig lo:3 127.0.0.3<br />" +
					"ect...<br /><br/>" +
					"Then in /etc/hosts add<br>" +
					"127.0.0.2       localhost2.localdomain  localhost2      lo2<br />" +
					"127.0.0.3       localhost3.localdomain  localhost3      lo3<br />" +
					"ect...<br/><br/>" +
					"And either restart or run the command<br />" +
					"<pre>source rc.local</pre>");
			someHtml.setStyleName("info");
			output.add(someHtml);
		}
		
		
	}
	
	
	protected void addAllEAPReleases() {
		jbossVersionField.addItem("EAP 5.1.0.Beta", "5.1.0.Beta");
		jbossVersionField.addItem("EAP 5.0.1.GA", "5.0.1");
		jbossVersionField.addItem("EAP 5.0.0.GA", "5.0.0");
		jbossVersionField.addItem("EAP 4.3.0.GA_CP08", "4.3.0.GA_CP08");
		jbossVersionField.addItem("EAP 4.3.0.GA_CP07", "4.3.0.GA_CP07");
		jbossVersionField.addItem("EAP 4.3.0.GA_CP06", "4.3.0.GA_CP06");
		jbossVersionField.addItem("EAP 4.3.0.GA_CP05", "4.3.0.GA_CP05");
		jbossVersionField.addItem("EAP 4.3.0.GA_CP04", "4.3.0.GA_CP04");
		jbossVersionField.addItem("EAP 4.3.0.GA_CP03", "4.3.0.GA_CP03");
		jbossVersionField.addItem("EAP 4.3.0.GA_CP02", "4.3.0.GA_CP02");
		jbossVersionField.addItem("EAP 4.3.0.GA_CP01", "4.3.0.GA_CP01");
		jbossVersionField.addItem("EAP 4.3.0.GA", "4.3.0.GA");
		jbossVersionField.addItem("EAP 4.2.0.GA_CP09", "4.2.0.GA_CP09");
		jbossVersionField.addItem("EAP 4.2.0.GA_CP08", "4.2.0.GA_CP08");
		jbossVersionField.addItem("EAP 4.2.0.GA_CP07", "4.2.0.GA_CP07");
		jbossVersionField.addItem("EAP 4.2.0.GA_CP06", "4.2.0.GA_CP06");
		jbossVersionField.addItem("EAP 4.2.0.GA_CP05", "4.2.0.GA_CP05");
		jbossVersionField.addItem("EAP 4.2.0.GA_CP04", "4.2.0.GA_CP04");
		jbossVersionField.addItem("EAP 4.2.0.GA_CP03", "4.2.0.GA_CP03");
		jbossVersionField.addItem("EAP 4.2.0.GA_CP02", "4.2.0.GA_CP02");
		jbossVersionField.addItem("EAP 4.2.0.GA_CP01", "4.2.0.GA_CP01");
	}
	
	protected void addOnlyEAP5OrGreaterReleases() {
		jbossVersionField.addItem("EAP 5.1.0.Beta", "5.1.0.Beta");
		jbossVersionField.addItem("EAP 5.0.1.GA", "5.0.1");
		jbossVersionField.addItem("EAP 5.0.0.GA", "5.0.0");
	}
	
	protected void addAllCommunityJBossReleases() {
		jbossVersionField.addItem("AS 6.0.0-M3", "6.0.0-M3");
		jbossVersionField.addItem("AS 5.1.0.GA", "5.1.0.GA");
		jbossVersionField.addItem("AS 5.0.1.GA", "5.0.1.GA");
		jbossVersionField.addItem("AS 5.0.0.GA", "5.0.0.GA");
		jbossVersionField.addItem("AS 4.2.3.GA", "4.2.3.GA");
		jbossVersionField.addItem("AS 4.2.2.GA", "4.2.2.GA");
	}
	
	protected void addOnlyCommunityJBoss5OrGreaterReleases() {
		jbossVersionField.addItem("AS 6.0.0-M3", "6.0.0-M3");
		jbossVersionField.addItem("AS 5.1.0.GA", "5.1.0.GA");
		jbossVersionField.addItem("AS 5.0.1.GA", "5.0.1.GA");
		jbossVersionField.addItem("AS 5.0.0.GA", "5.0.0.GA");
	}
	
	protected void addOnlyCommunityJBoss51OrGreaterReleases() {
		jbossVersionField.addItem("AS 6.0.0-M3", "6.0.0-M3");
		jbossVersionField.addItem("AS 5.1.0.GA", "5.1.0.GA");
	}
	
	private void addItemsToListBox(ListBox listBox, String... strings) {
		for(String s : strings) {
			listBox.addItem(s);
		}
	}
	
	private void setVisible(boolean visible, Widget... widgets) {
		if(visible) {
			for(Widget w : widgets) {
				w.setVisible(true);
			}
		} else {
			for(Widget w : widgets) {
				w.setVisible(false);
			}
		}
	}

}
